<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>promise多并发请求</title>
  </head>
  <script>
    // 参考博客：http://www.inspinia.net/a/895377.html?action=onClick

    /**
     * 并发请求
     * @param {string[]} url 待请求的 url 数组
     * @param {number} maxNum 最大并发数
     */
    const multiConcurrentRequests = (urls, maxNum) => {
      return new Promise((resolve, reject) => {
        if (urls.length === 0) {
          resolve([]);
          return;
        }

        // results 用来存储所有请求的结果 index 下一个请求的下标, count 当前请求完成的数量
        let results = [], index = 0, count = 0;

        const request = async () => {
          // 当index等于数组的长度表示完成
          if (index === urls.length) return;
          const i = index;
          let url = urls[index];
          // 确保在请求完成之前，i 的值与 index 的值相同。
          index++;
      
          try {
            const res = await fetch(url);
            results[i] = res;
          } catch (error) {
            results[i] = error;
          } finally {
            count++;
            // 无论是请求成功还是请求失败都会走这里
            if (count === urls.length) {
              // 所有的请求都已经完成
              resolve(results);
            }
            // 如没有请求完，则继续请求
            request();
          }
        };

        const times = Math.min(maxNum, urls.length);
        for (let i = 0; i < times; i++) {
          request();
        }
      });
    };

    // 模拟请求
    const https = [];
    for (let i = 1; i <= 20; i++) {
      https.push(`https://jsonplaceholder.typicode.com/todos/${i}`);
    }
    multiConcurrentRequests(https, 6).then((res) => {
      console.log('res=', res);
    });
  </script>
</html>
